/**
 * Created by Administrator on 17-9-29.
 */
var  iconst=require('./iconst');
var  cardStruct=require('./cardStruct');
var  core_10dban=require('./core_d89');
var  stateMachine=require('./stateMachine');
var     P = require("bluebird");
var  util=require('./util');
var     redis;
var     userDao;

var room=function(roomId,roomManage)
{
    this.m=[];
    this.roomManage=roomManage;
    redis=roomManage.redis;
    userDao=roomManage.userDao;
    this.redis=redis;
    this.userDao=userDao;
    this.createCount=0;

    this.roomInfo={};
    this.roomId=roomId;
    this.roomPsw=null;
    this.set('roomId',roomId);
    this.set('roomPsw',null);
    this.set('ownerUid',-1);
    this.set('userList',[]);
    this.set('viewerList',[]);
    this.set('seatMap',{});
    this.set('userMap',{});
    this.set('gameCount',0);//最大局数
    this.set('gamingCount',0);//当前第几局
    this.set('timeLeft',0);
    this.set('gameResult',{});
    this.set('gameStatus','onIdle');
    this.set('countDownTime',10);
    this.set('countDownTick',new Date().getTime());
    this.set('bankUid',-1);
    this.set('releaseRoom',0);
    this.sm=new stateMachine('gameD89');
    this.sm.setCallback('onIdle',this.onIdle.bind(this),iconst.timeout.onIdle);
    this.sm.setCallback('waitReady',this.waitReadyEnd.bind(this),iconst.timeout.waitReady);
    this.sm.setCallback('waitQiangzhuang',this.waitQiangzhuangEnd.bind(this),iconst.timeout.waitQiangzhuang);
    this.sm.setCallback('waitBetting',this.waitBettingEnd.bind(this),iconst.timeout.waitBetting);
    this.sm.setCallback('waitTanpai',this.waitTanpaiEnd.bind(this),iconst.timeout.waitTanPai);
    this.sm.setCallback('showGameResult',this.showGameResultEnd.bind(this),iconst.timeout.showGameResult);
    this.sm.setCallback('showFinalResult',this.showFinalResultEnd.bind(this),iconst.timeout.showFinalResult);
    this.sm1=new stateMachine('releaseGame');
    this.sm1.setCallback('onIdle',this.onIdleRelease.bind(this),iconst.timeoutRelease.onIdle);
    this.sm1.setCallback('waitReady',this.waitReadyEndRelease.bind(this),iconst.timeoutRelease.waitReady);
    this.sm1.setCallback('waitBetting',this.waitBettingEndRelease.bind(this),iconst.timeoutRelease.waitBetting);
   //this.sm1.setCallback('showGameResult',this.showGameResultEnd.bind(this),iconst.timeoutRelease.showGameResult);
    this.sm1.setCallback('showFinalResult',this.showFinalResultEnd.bind(this),iconst.timeoutRelease.showFinalResult);
    this.sm1.setCallback('nobodyActive',this.nobodyActiveEnd.bind(this),iconst.timeoutRelease.nobodyActive);
    this.sm1.changeState('nobodyActive');
    this.extraData={};
}

room.prototype.changeState=function(state)
{   this.set('countDownTick',new Date().getTime());
    this.set('gameStatus',state);
    this.extraData.status=state;
    var  nTime=this.sm.getStateTime(state);
    if(nTime>0) this.set('countDownTime',nTime);else this.set('countDownTime',10);
    this.sm.changeState(state);
    this.sm1.changeState('nobodyActive');
}

room.prototype.get=function(key)
{
    return this.m[key];
}

room.prototype.set=function(key,value)
{
    this.m[key]=value;
}

room.prototype.sendMsgByUid=function(uid,msg)
{
    this.roomManage.sendByRoom(this.roomId,uid,msg);
}

room.prototype.send2gamingUsers=function(msg)
{
    var list=this.get('userList');
    var  len=list.length;
    for(var i=0;i<len;i++)
    {   var user=list[i];
        if(user.gaming==1&&user.online==1)
        {   this.roomManage.sendByRoom(this.roomId,user.uid,msg);}
    }
}

room.prototype.sendByUid=function(uid,msg)
{  this.roomManage.sendByRoom(this.roomId,uid,msg);
}

room.prototype.send2All=function(msg)
{
    var list=this.get('userList');
    var  len=list.length;
    for(var i=0;i<len;i++)
    {    var user=list[i];
        if(user.online==1)
        {this.roomManage.sendByRoom(this.roomId,user.uid,msg);}
    }
}
room.prototype.notifyPrivate=function()
{
    var list=this.get('userList');
    var  len=list.length;
    var  gameStatus=this.get('gameStatus');
    if(gameStatus=='waitReady'||gameStatus=='onIdle'||gameStatus=='showGameResult')
        return;
    var  gameType=this.get("gameType");
    if(gameStatus=='waitTanpai'&&gameType==iconst.d89.gameTypeTongbi)
    { return;}
    for(var i=0;i<len;i++)
    {
        var user=list[i];
        if(user.gaming==1&&user.playing==1&&user.cardItem)
        {
            var cards=user.cardItem.cards;
            var  clist=[cards[0].cid,-1];
            if(user.tanpai==1)
            {
                clist=[cards[0].cid,cards[1].cid];
            }
            var msg={event:iconst.event.privateInfo,cards:clist};
            this.sendByUid(user.uid,msg);
        }
    }
}
room.prototype.notifyUpdate=function(uid)
{
    var list=this.get('userList');
    var  len=list.length;
    if(len==0) return;
    var  publicInfo=[];
    var  cardsMap={};
    var  bank=this.getUser(this.get('bankUid'));
    var  bankUid=-1;
    var  gameType=this.get("gameType");
    if(bank)   bankUid=bank.uid;
    for(var i=0;i<len;i++)
    {   var user=list[i];
        var item={name:user.name,headimgurl:user.headimgurl,uid:user.uid,online:user.online,gaming:user.gaming,online:user.online,seatId:user.seatId,
        playing:user.playing,ip:user.ip,bet:user.bet,totalBet:user.totalBet,cardNum:user.cardNum,
            score:user.score,bankUid:bankUid,zbet:user.zbet,cardsShow:user.cardsShow,tanpai:user.tanpai};
        if(user.gaming==1&&user.playing==1&&user.cardItem&&user.tanpai==1)
        {cardsMap[user.uid]={cards:user.cardItem.cards,type:user.cardItem.type,dian:user.cardItem.dian};}
        publicInfo.push(item);
    }
    var  leftTime=this.getLeftTime();
    var  goingTime=this.getGoingTime();
    var  gameStatus=this.get('gameStatus');
    var  process=this.get('gamingCount')+'/'+this.get('gameCount');
    var  msg={event:iconst.event.updateTable,publicInfo:publicInfo,maxPlayer:iconst.maxPlayer,roomId:this.roomPsw,
        gameStatus:gameStatus,process:process,fn:this.fn,gameType:gameType,
        leftTime:leftTime,goingTime:goingTime,extraData:this.extraData,bankUid:this.get('bankUid'),
        roomInfo:this.roomInfo
    };
    if(gameStatus=='showGameResult'||gameStatus=="waitTanpai")
    { msg.cardsMap=cardsMap;
    }
    if(uid==undefined)
        this.send2All(msg);
    else
        this.sendByUid(uid,msg);
    this.extraData={};
    this.notifyPrivate();
}

room.prototype.send2viewers=function(msg)
{

}

room.prototype.getUserInfo=function(uid)
{
    var info=this.roomManage.getUserInfo(uid);
    if(!info)
    {console.logr(this.get('roomPsw'),'null userInfo ',uid);}
    return info;
};

room.prototype.getUser=function(uid)
{
    var map=this.get('userMap');
     return map[uid];
};
room.prototype.gameInit=function()
{
    this.roomInfo={gameType:this.get('gameType'),
        diFeng:this.get("diFeng"),
        gameRule:this.get('gameRule'),
        gameCount:this.get('gameCount')};
    this.roomInfo.fanbeiType=this.get('gameRule');
    this.roomInfo.qiangzhuangType=this.get('gameType');
    this.roomInfo.wuhua=0;
    this.roomInfo.zhadan=0;
    this.roomInfo.wuxiao=0;
    this.roomInfo.shangzhuangFenshu=0;
    this.roomInfo.playType=this.get('gameType');
    this.roomInfo.hand_patterns=[0,0,0];//五花，炸弹，五小
    this.roomInfo.upper_limit=0;
    this.roomInfo.end_points=this.get('diFeng');//分
    var   nCard=this.get('cardRequire');
    this.roomInfo.need_cards=nCard; //需要的房卡
    this.roomInfo.end_points=this.get('diFeng');//地分
    var  tick=new Date().getTime();
    this.set('startTime',util.tick2DateStr(tick));
}
room.prototype.checkCardRequire=function(uid,createData)
{
    var info=this.getUserInfo(uid);
    if(!info)
    {   console.logr(this.roomPsw,'invalid user info in newUserStatus');
        this.sendMsgByUid(uid,{event:iconst.event.error,msg:'用户信息异常'});
        return false;
    }
    var gameCount=createData.gameCount;
    if(createData.innerGameType!=undefined)  createData.gameType=createData.innerGameType;
    if(gameCount==12||gameCount==24)
    { this.set('gameCount',gameCount);
    }else { console.logr(this.roomPsw,'非法的 gameCount',uid,gameCount);this.set('gameCount',12);}
    var  n=this.get('gameCount')/12;
    var  nCard=n*2;
    this.set('gameType',iconst.d89.gameTypeQiangzhuang);
    if(createData.gameType==iconst.d89.gameTypeTongbi) this.set('gameType',iconst.d89.gameTypeTongbi);
    if(createData.gameType==iconst.d89.gameTypeGudingZhuangjia) this.set('gameType',iconst.d89.gameTypeGudingZhuangjia);
    this.set('gameRule',iconst.d89.fanbei);
    if(createData.gameRule==iconst.d89.bufanbei)  this.set('gameRule',iconst.d89.bufanbei);
    this.set("diFeng",1);
    var  diFeng=Math.floor(Number(createData.diFeng));
    if(diFeng>0&&diFeng<=5)  this.set("diFeng",diFeng);


    this.set('cardRequire',nCard);
    var  cardRequire=nCard;
    this.gameInit();
    if(info.cardNum<cardRequire)
    {
        console.logr(this.roomPsw,'玩家钻石不足,不能创建房间',uid,info.name,info.cardNum);
        this.sendMsgByUid(uid,{event:iconst.event.error,msg:'钻石不足请充值'});
        return false;
    }
    return true;
};
room.prototype.newPlayer=function(uid)
{
    var info=this.getUserInfo(uid);
    var  player={uid:uid,name:info.name,wxNickName:info.wxNickName,headimgurl:info.headimgurl,cardNum:info.cardNum,online:1,gaming:0,playing:0,bet:0,
        totalBet:0,zbet:0,score:0,cardConsume:0,tanpai:0,cuopai:0,
    ip:info.ip};
    console.logr(this.roomPsw,'newPlayer',player);
    var map=this.get('userMap');
    var list=this.get('userList');
    list.push(player);
    map[uid]=player;
    return player;
}

room.prototype.removePlayer=function(uid)
{
    var list=this.get('userList');
    var len=list.length;
    var  newList=[];
    for(var i=0;i<len;i++)
    {  var player=list[i];
        if(player.uid==uid)
        {
            console.logr(this.roomPsw,'移除玩家',uid,player.name);
            continue;
        }
        newList.push(player);
    }
    this.set('userList',newList);
    var map=this.get('userMap');
    map[uid]=null;
}
room.prototype.getRoomPsw=function()
{
    return this.roomPsw;
};

room.prototype.dataReinit=function(uid)
{
    console.logr(this.roomPsw,'dataReinit',uid);
    this.set('userList',[]);
    this.set('seatMap',{});
    this.set('userMap',{});
    this.set('gameCount',0);//最大局数
    this.set('gamingCount',0);//当前第几局
    this.set('timeLeft',0);
    this.set('gameResult',{});
    this.set('gameStatus','onIdle');
    this.set('countDownTime',10);
    this.set('countDownTick',new Date().getTime());
    //this.set('bankUid',-1);
    this.set('guestMap',{});
}

room.prototype.createRoom=function(uid,createData,psw)
{
    console.logg("createRoom",uid,psw,createData);
    this.roomManage.bindRoomSocket(this.roomId,uid);
    this.dataReinit(uid);
    var ret=this.checkCardRequire(uid,createData);
    if(ret==false)
    { return -1;}
    if(createData.gameType==iconst.d89.gameTypeGudingZhuangjia)
    {
        this.set("bankUid",uid);
    }
    this.createCount++;
    this.set('roomPsw',psw);
    this.set('releaseRoom',0);
    this.roomPsw=psw;
    console.logr(this.roomPsw,'玩家创建房间',uid);
    var  list=[];
    var  map={};
    this.set('userList',list);
    this.set('userMap',map);
    var player=this.newPlayer(uid);
    this.set('gamingCount',0);//当前第几局
    this.set('gameResult',{});//创建房间的时候重新置为空
    player.seatId=0;
    player.gaming=1;
    this.fn=0;
    var map=this.get('seatMap');
    this.set('ownerUid',uid);
    map={};///这个是bug
    //this.set('seatMap',{});
    this.userSeatDown(uid);
    this.notifyUpdate();
    return this.roomId;
}
room.prototype.getUserRedisRoomInfo= P.coroutine(function*(uid,createData)
{   var  user_id='user_'+uid;
    var  room=yield redis.getHashItem(iconst.gameHistoryName,user_id);
    if(!room) return null;
    var  roomInfo=yield redis.getHashItem(iconst.gameHistoryName,room);
    try
    { roomInfo=JSON.parse(roomInfo);
    }
    catch(e)
    {
        roomInfo=null;
    }
    if(roomInfo)
    {//                roomInfo={owner:uid,rid:rid,roomId:randomId,roomPsw:randomId,tick:n,gameType:'d89',gameCount:rm.get('gameCount'),
        //name:userInfo.name,headimgurl:userInfo.headimgurl,gameStatus:'create',
        //serverName:self.serverName,
        //innerGameType:createData.gameType,diFeng:createData.diFeng};

        if(roomInfo.innerGameType==iconst.d89.gameTypeGudingZhuangjia)
        {   console.logr(this.roomPsw,'固定庄家模式只能创建一次房间',uid);
            return roomInfo;
        }
    }
    return null;
});
room.prototype.createRoomSync= P.coroutine(function*(uid,createData,psw)
{
    console.logg("createRoom",uid,psw,createData);
        var  roomInfo=yield this.getUserRedisRoomInfo(uid);
        if(roomInfo)  {
            console.logg('玩家创建房间失败，固定庄家模式只能创建一次',uid);
            return -2;
        }
        this.dataReinit(uid);
        this.roomManage.bindRoomSocket(this.roomId,uid);
        var ret=this.checkCardRequire(uid,createData);
        if(ret==false)
        { return -1;}

        this.createCount++;
        this.set('roomPsw',psw);
        this.set('releaseRoom',0);
        this.roomPsw=psw;
        console.logr(this.roomPsw,'玩家创建房间',uid);
        var  list=[];
        var  map={};
        this.set('userList',list);
        this.set('userMap',map);
        var player=this.newPlayer(uid);
        this.set('gamingCount',0);//当前第几局
        this.set('gameResult',{});//创建房间的时候重新置为空
        player.seatId=0;
        player.gaming=0;
        this.fn=0;
        var map=this.get('seatMap');
        this.set('ownerUid',uid);
        //map={};///这个是bug
        this.set('seatMap',{});
        this.userSeatDown(uid);
    if(createData.gameType==iconst.d89.gameTypeGudingZhuangjia)
    {
        this.set("bankUid",uid);
        player.gaming=1;
        console.logr(this.roomPsw,'固定庄家模式，房主当庄',uid);
        this.recordUserRoomInfo(uid);
    }
        yield this.decUserCard(player);
        this.notifyUpdate();
        return this.roomId;

});


room.prototype.userKeepAlive=function(uid)
{
    var status=this.getUserInfo(uid);
    if(!status) return;
    status.aliveTick=new Date().getTime();
};

room.prototype.isCanEnterRoom=function(uid)
{
    return true;
    var info=this.getUserInfo(uid);
    var  cardRequire=this.get('cardRequire');
    var  cardType=this.get('cardType');
    if(cardType==iconst.d89.FangzhuFufei)
        return true;
    if(info.cardNum>=cardRequire)
    { return true;}
    return false;
};

room.prototype.enterRoom=function(uid,msg)
{
    this.roomManage.bindRoomSocket(this.roomId,uid);
    var info=this.getUserInfo(uid);
    console.logr(this.roomPsw,'玩家进入房间',uid,info.name);
    var  list=this.get('userList');
    var  len=list.length;
    var   userInfo=this.getUser(uid);
    if(userInfo&&userInfo.seatId!=undefined)
    {   userInfo.online=1;
        this.extraData.event='enterRoom';
        this.notifyUpdate();
        console.logr(this.roomPsw,'玩家已在房间中直接进入房间',uid,userInfo.name);
        return true;
    }
    var  canEnter=this.isCanEnterRoom(uid);
    if(!canEnter)
    {
        console.logr(this.roomPsw,'房卡不足',uid,info.name);
        this.sendByUid(uid,{event:iconst.event.error,msg:'房卡不足'});
        return  false;
    }
    if(len>=iconst.maxPlayer)
    {
        console.logr(this.roomPsw,'已经超过人数限制不能再进入房间',uid);
        this.sendMsgByUid(uid,{event:iconst.event.error,msg:'房间已满'});
        return false;
    }
    var  player;
    var  map=this.get('userMap');
    player=map[uid];
    if(!player)
    { this.newPlayer(uid);}
    else
    {player.online=1;}
    this.userSeatDown(uid);
    this.extraData.event='enterRoom';
    this.notifyUpdate();
    return true;
}

room.prototype.exitRoom=function(uid)
{
    this.roomManage.unbindRoomSocket(this.roomId,uid);
    var  map=this.get('userMap');
    var info=this.getUserInfo(uid);
    console.logr(this.roomPsw,'玩家掉线',uid,info.name);
    if(this.roomPsw==null)
    {   console.logr(this.roomPsw,'房间为空清理 userlist userMap',uid,info.name,this.roomPsw);
        this.set('userList',[]);
        this.set('userMap',{});
    }
    var  player=map[uid];
    if(!player)
    {   console.logr(this.roomPsw,'exitRoom player 为空',uid,info.name);
        return;
    }
    if(player.gaming==1)
    { player.online=0;}
    else
    {   this.userSeatUp(uid);
        this.removePlayer(uid);
    }
    var  list=this.get('userList');
    var len=list.length;
    this.notifyUpdate();
    if(len==0)
    { //this.destroyRoom();
    }
}

room.prototype.userQuery=function()
{   this.notifyUpdate();
}

room.prototype.destroyRoom=function()
{
    console.logr(this.roomPsw,'清理房间 ',this.roomPsw);
    var  roomPsw=this.roomPsw;
    this.roomPsw=null;
    var  list=this.get('userList');
    var len=list.length;
    for(var i=0;i<len;i++)
    {   var user=list[i];
        if(!user)  continue;
        this.userSeatUp(user.uid);
        this.roomManage.clearUserRoom(user.uid);
    }

    this.set('userList',[]);
    this.set('userMap',{});
    var self=this;
    var doAsync= P.coroutine(function*()
    {
        yield redis.delHashItem('d89_roomMap','r'+roomPsw);
        yield redis.delHashItem(iconst.gameHistoryName,'room_'+roomPsw);
        console.logr(roomPsw,'销毁redis房间记录',roomPsw);
        self.changeState('onIdle');
    });
    doAsync().catch(function(e)
    {
        console.logr(roomPsw,'destroyRoom exception ', e.message);
    });

};

room.prototype.releaseRoom=function(uid)
{
    var info=this.getUserInfo(uid);

}

room.prototype.recordUserRoomInfo=function(uid)
{
    var self=this;
    var doAsync= P.coroutine(function*()
    {
        var key='user_'+uid;
        var value='room_'+self.roomPsw;
        console.logr(self.roomPsw,'记录玩家房间号信息',uid,self.roomPsw);
        yield redis.setHashItem(iconst.gameHistoryName,key,value);
    });
    doAsync().catch(function(e)
    {
        console.logg('recordUserRoomInfo exception ',e);
    });
};

room.prototype.clearUserRoomInfo=function(uid)
{
    var self=this;
    var doAsync= P.coroutine(function*()
    {
        var key='user_'+uid;
        console.logg('清理玩家房间号信息',uid,self.roomPsw);
        yield redis.delHashItem(iconst.gameHistoryName,key);
    });
    doAsync().catch(function(e)
    { console.logg('recordUserRoomInfo exception ',e);
    });
};

room.prototype.userSeatDown=function(uid)
{
    var   map=this.get('seatMap');
    var   info=this.getUser(uid);
    var   list=this.get('userList');
    console.logr(this.roomPsw,'玩家 try seatDown',uid,info.name,info.seatId);
    for(var i=0;i<iconst.maxPlayer;i++)
    {
        var user=map[i];
        if(user==null||user==undefined)
            continue;
        if(user.uid==uid)
        {   console.logr(this.roomPsw,'玩家',uid,info.name,'已经坐下座位id',user.seatId);
            user.seatId=i;
            break;
        }
    }
    for(var i=0;i<iconst.maxPlayer;i++)
    {
        var user=map[i];
        if(user==null||user==undefined)
        {   map[i]=info;
            info.seatId=i;
            //list.push(info);
            //this.recordUserRoomInfo(uid);
            console.logr(this.roomPsw,'玩家',uid,info.name,'seatDown',list.length,'座位号',info.seatId);
            return true;
        }
    }
    console.logr(this.roomPsw,'玩家',uid,info.name,'can not seat down',info.seatId);
    return false;
}

room.prototype.userSeatUp=function(uid)
{
    var   map=this.get('seatMap');
    var   info=this.getUserInfo(uid);
    for(var i=0;i<iconst.maxPlayer;i++)
    {    var user=map[i];
        if(user==null||user==undefined)
            continue;
        if(user.uid==uid)
        {   map[i]=null;
            user.seatId=-1;
            console.logr(this.roomPsw,'user seatup ',uid,info.name);
            //this.clearUserRoomInfo(uid);
            return true;
        }
    }
    return false;
}

room.prototype.getUserCount=function()
{
    var  list=this.get('userList');
    var  n=0;
    if(!list) n=0;
    else n=list.length;
    for(var i in list)
    {
        var  user=list[i];
        var  uid=user.uid;
        var  info=this.getUserInfo(uid);
        var  time=(new Date().getTime()-info.liveTick)/1000;
        if(time>iconst.keepAliveTime)
        {
            if(user.online==1)
            {user.online=0;
                console.logr(this.roomPsw,'玩家超时没有心跳包，判定为断线',uid,user.name);
                this.roomManage.forceKick(user.uid);
            }
        }
    }
    if(this.roomPsw!=null)  n++;
    return n;
}

room.prototype.notifyPublic=function(msg)
{

}

room.prototype.notifyGamingUser=function(msg)
{

}

room.prototype.onUpdate=function()
{
    if(this.loopTick==undefined)  this.loopTick=new Date().getTime();
    var  time=(new Date().getTime()-this.loopTick)/1000;
    if(time>5)
    {
        //this.notifyUpdate();
        this.loopTick=new Date().getTime();
    }
    this.sm.onLoop();
    this.sm1.onLoop();
};
module.exports=room;
require('./room_d89_action');
require('./room_d89_status');
require('./room_d89_release');